<template>
    <div>
        <div id="container1"></div>
    </div>
</template>
<script setup>
import { onMounted } from 'vue';
import { Graph, Cell, Node, Dom } from '@antv/x6';
import dagre from 'dagre';

// 自定义节点
Graph.registerNode(
    'org-node',
    {
        width: 260,
        height: 88,
        markup: [
            {
                tagName: 'rect',
                attrs: {
                    class: 'card',
                },
            },
            {
                tagName: 'image',
                attrs: {
                    class: 'image',
                },
            },
            {
                tagName: 'text',
                attrs: {
                    class: 'rank',
                },
            },
            {
                tagName: 'text',
                attrs: {
                    class: 'name',
                },
            },
            {
                tagName: 'g',
                attrs: {
                    class: 'btn add',
                },
                children: [
                    {
                        tagName: 'circle',
                        attrs: {
                            class: 'add',
                        },
                    },
                    {
                        tagName: 'text',
                        attrs: {
                            class: 'add',
                        },
                    },
                ],
            },
            {
                tagName: 'g',
                attrs: {
                    class: 'btn del',
                },
                children: [
                    {
                        tagName: 'circle',
                        attrs: {
                            class: 'del',
                        },
                    },
                    {
                        tagName: 'text',
                        attrs: {
                            class: 'del',
                        },
                    },
                ],
            },
        ],
        attrs: {
            '.card': {
                rx: 10,
                ry: 10,
                refWidth: '100%',
                refHeight: '100%',
                fill: '#5F95FF',
                stroke: '#5F95FF',
                strokeWidth: 1,
                pointerEvents: 'visiblePainted',
            },
            '.image': {
                x: 16,
                y: 16,
                width: 56,
                height: 56,
                opacity: 0.7,
            },
            '.rank': {
                refX: 0.95,
                refY: 0.5,
                fill: '#fff',
                fontFamily: 'Courier New',
                fontSize: 13,
                textAnchor: 'end',
                textVerticalAnchor: 'middle',
            },
            '.name': {
                refX: 0.95,
                refY: 0.7,
                fill: '#fff',
                fontFamily: 'Arial',
                fontSize: 14,
                fontWeight: '600',
                textAnchor: 'end',
            },
            '.btn.add': {
                refDx: -16,
                refY: 16,
                event: 'node:add',
            },
            '.btn.del': {
                refDx: -44,
                refY: 16,
                event: 'node:delete',
            },
            '.btn > circle': {
                r: 10,
                fill: 'transparent',
                stroke: '#fff',
                strokeWidth: 1,
            },
            '.btn.add > text': {
                fontSize: 20,
                fontWeight: 800,
                fill: '#fff',
                x: -5.5,
                y: 7,
                fontFamily: 'Times New Roman',
                text: '+',
            },
            '.btn.del > text': {
                fontSize: 28,
                fontWeight: 500,
                fill: '#fff',
                x: -4.5,
                y: 6,
                fontFamily: 'Times New Roman',
                text: '-',
            },
        },
    },
    true
);

// 自定义边
Graph.registerEdge(
    'org-edge',
    {
        zIndex: -1,
        attrs: {
            line: {
                strokeWidth: 2,
                stroke: '#A2B1C3',
                sourceMarker: null,
                targetMarker: null,
            },
        },
    },
    true
);

const male = 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*kUy8SrEDp6YAAAAAAAAAAAAAARQnAQ';
const female = 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*f6hhT75YjkIAAAAAAAAAAAAAARQnAQ';
// 布局方向
const dir = 'LR'; // LR RL TB BT
// import insertCss from 'insert-css';
// // 定义样式
// // 我们用 insert-css 演示引入自定义样式
// // 推荐将样式添加到自己的样式文件中
// // 若拷贝官方代码，别忘了 npm install insert-css
// insertCss(`
//   .x6-cell {
//     cursor: default;
//   }
//   .x6-node .btn {
//     cursor: pointer;
//   }
// `)
onMounted(() => {
    // 创建画布
    const graph = new Graph({
        width: 1000,
        height: 600,
        container: document.getElementById('container1'),
        scroller: true,
        interacting: false,
    });

    // 监听自定义事件
    function setup() {
        graph.on('node:add', ({ e, node }) => {
            e.stopPropagation();
            const member = createNode('Employee', 'New Employee', Math.random() < 0.5 ? male : female);
            graph.freeze();
            graph.addCell([member, createEdge(node, member)]);
            layout();
        });

        graph.on('node:delete', ({ e, node }) => {
            e.stopPropagation();
            graph.freeze();
            graph.removeCell(node);
            layout();
        });
    }

    // 自动布局
    function layout() {
        const nodes = graph.getNodes();
        const edges = graph.getEdges();
        const g = new dagre.graphlib.Graph();
        g.setGraph({ rankdir: dir, nodesep: 16, ranksep: 16 });
        g.setDefaultEdgeLabel(() => ({}));

        const width = 260;
        const height = 90;
        nodes.forEach((node) => {
            g.setNode(node.id, { width, height });
        });

        edges.forEach((edge) => {
            const source = edge.getSource();
            const target = edge.getTarget();
            g.setEdge(source.cell, target.cell);
        });

        dagre.layout(g);

        graph.freeze();

        g.nodes().forEach((id) => {
            const node = graph.getCell(id);
            if (node) {
                const pos = g.node(id);
                node.position(pos.x, pos.y);
            }
        });

        edges.forEach((edge) => {
            const source = edge.getSourceNode();
            const target = edge.getTargetNode();
            const sourceBBox = source.getBBox();
            const targetBBox = target.getBBox();

            console.log(sourceBBox, targetBBox);

            if ((dir === 'LR' || dir === 'RL') && sourceBBox.y !== targetBBox.y) {
                const gap =
                    dir === 'LR'
                        ? targetBBox.x - sourceBBox.x - sourceBBox.width
                        : -sourceBBox.x + targetBBox.x + targetBBox.width;
                const fix = dir === 'LR' ? sourceBBox.width : 0;
                const x = sourceBBox.x + fix + gap / 2;
                edge.setVertices([
                    { x, y: sourceBBox.center.y },
                    { x, y: targetBBox.center.y },
                ]);
            } else if ((dir === 'TB' || dir === 'BT') && sourceBBox.x !== targetBBox.x) {
                const gap =
                    dir === 'TB'
                        ? targetBBox.y - sourceBBox.y - sourceBBox.height
                        : -sourceBBox.y + targetBBox.y + targetBBox.height;
                const fix = dir === 'TB' ? sourceBBox.height : 0;
                const y = sourceBBox.y + fix + gap / 2;
                edge.setVertices([
                    { x: sourceBBox.center.x, y },
                    { x: targetBBox.center.x, y },
                ]);
            } else {
                edge.setVertices([]);
            }
        });

        graph.unfreeze();
    }

    function createNode(rank, name, image) {
        return graph.createNode({
            shape: 'org-node',
            attrs: {
                '.image': { xlinkHref: image },
                '.rank': {
                    text: Dom.breakText(rank, { width: 160, height: 45 }),
                },
                '.name': {
                    text: Dom.breakText(name, { width: 160, height: 45 }),
                },
            },
        });
    }

    function createEdge(source, target) {
        return graph.createEdge({
            shape: 'org-edge',
            source: { cell: source.id },
            target: { cell: target.id },
        });
    }

    const nodes = [
        createNode('Founder & Chairman', '大伟聊前端1', male),
        createNode('President & CEO', '大伟聊前端2', female),
        createNode('President, PayPal', '大伟聊前端3', male),
        createNode('President, Ebay Global Marketplaces', '大伟聊前端4', male),
        createNode('Senior Vice President Human Resources', '大伟聊前端5', male),
        createNode('Senior Vice President Controller', '大伟聊前端6', male),
    ];

    const edges = [
        createEdge(nodes[0], nodes[1]),
        createEdge(nodes[1], nodes[2]),
        createEdge(nodes[1], nodes[3]),
        createEdge(nodes[1], nodes[4]),
        createEdge(nodes[1], nodes[5]),
    ];

    graph.resetCells([...nodes, ...edges]);
    layout();
    graph.zoomTo(0.8);
    graph.centerContent();
    setup();
});
</script>
